#include "asynframeimpl.h"
#include "tcpsocketimpl.h"
#include "tcpsocketsslimpl.h"
#include "udpsocketimpl.h"
#include "tcplistensocketimpl.h"
#include "tcplistensocketsslimpl.h"
#include "timerimpl.h"
#include "iooperationimpl.h"
#include "pipeimpl.h"
#include "spipeimpl.h"

CAsynFrameImpl::CAsynFrameImpl(void)
{
    m_eventindex = 0;
}

CAsynFrameImpl::~CAsynFrameImpl(void)
{
    logi("CAsynFrameImpl::~CAsynFrameImpl");
}

static int eventloop_time_notify(ioevloop_t* evloop, int index)
{
    rc_error(evloop != NULL, S_ERROR);
    CAsynFrameImpl* frame = (CAsynFrameImpl*)ioevloop_getctx(evloop);
    rc_error(frame != NULL, S_ERROR);
    logi("Send Semp");
    frame->PostComplete(index);
    return S_SUCCESS;
}
static void eventloop_time(int sock, short event, void* arg)
{
    rc_return(arg != NULL);
    struct ioevloop_s* ev = (struct ioevloop_s*)(arg);
    rc_return(ev != NULL);
    rc_return(ev->notify != NULL);
    ev->notify(ev, IOEV_NOTIFY_TYPE_WORK);
}

HRESULT CAsynFrameImpl::Init(IBase* pRot, IBase* pBase)
{
    rc_error(pRot != NULL, E_FAIL);

    HRESULT hr = S_OK;
    hr = pRot->QueryInterface(IID_IRot, (void**)&m_pRot);
    rc_error(hr == S_OK, E_FAIL);

    InitEventLoop();

    this->m_tpcount = 4;
    this->m_evloop = (ioevloop_t*)heap_malloc(this->m_tpcount * sizeof(ioevloop_t));

    unsigned int index = 0;
    for (index = 0; index < this->m_tpcount; index++) {
        ioevloop_t* ev = this->m_evloop + index;
        CreateEventLoop(ev, eventloop_time_notify, this);
    }

    return S_OK;
}
HRESULT CAsynFrameImpl::Uninit()
{
    return S_OK;
}
HRESULT CAsynFrameImpl::Start(_pid_t pid, unsigned int type)
{
    init_sockenv(2, 0);

    CThreadPool::StartThreadPool(m_tpcount);

    unsigned int index = 0;
    for (index = 0; index < this->m_tpcount; index++) {
        // this->m_sem.Wait();
    }

    return S_OK;
}
HRESULT CAsynFrameImpl::Stop(unsigned int exit)
{
    unsigned int index = 0;

    for (index = 0; index < this->m_tpcount; index++) {
        ioevloop_t* ev = this->m_evloop + index;
        ExitEventLoop(ev);
    }

    for (index = 0; index < this->m_tpcount; index++) {
        this->m_exitsem.Wait();
    }

    CThreadPool::StopThreadPool();
    uninit_sockenv(2, 0);

    return S_OK;
}
HRESULT CAsynFrameImpl::CreateIo(IO_Protocol iop, IBase** pBase)
{
    if (io_operation == iop)
        return CreateIOperation(pBase);
    else if (io_tcp_socket == iop)
        return CreateITcpSocket(pBase);
    else if (io_tcplisten_socket == iop)
        return CreateITcpListenSocket(pBase);
    else if (io_udp_socket == iop)
        return CreateIUdpSocket(pBase);
    else if (io_udplisten_socket == iop)
        return E_FAIL;
    else if (io_tcp_ssl_socket == iop)
        return CreateITcpSocketSSL(pBase);
    else if (io_tcplisten_ssl_socket == iop)
        return CreateITcpListenSSLSocket(pBase);
    else if (io_timer == iop)
        return CreateITimer(pBase);
    else if (io_pipe == iop)
        return CreateIPipe(pBase);
    else if (io_spipe == iop)
        return CreateISPipe(pBase);

    return E_FAIL;
}
HRESULT CAsynFrameImpl::PostIo(IBase* pOperation)
{
    int rc = S_SUCCESS;
    return rc == S_SUCCESS ? S_OK : E_FAIL;
}

HRESULT CAsynFrameImpl::ThreadPool_Run(void* user, void* ctx)
{
    rc_error(ctx != NULL, E_FAIL);
    io_thread_t* thread = (io_thread_t*)(ctx);
    rc_error(thread != NULL, E_FAIL);
    ioevloop_t* ev = m_evloop + thread->id;
    rc_error(ev != NULL, E_FAIL);
    RunEventLoop(ev);
    return S_OK;
}
HRESULT CAsynFrameImpl::PostComplete(int type)
{
    if (IOEV_NOTIFY_TYPE_WORK == type) {
        this->m_sem.Post();
    }

    if (IOEV_NOTIFY_TYPE_EXIT == type) {
        this->m_exitsem.Post();
    }

    return S_OK;
}
HRESULT CAsynFrameImpl::ThreadPool_Start()
{
    return S_OK;
}
HRESULT CAsynFrameImpl::ThreadPool_Stop()
{
    return S_OK;
}
HRESULT CAsynFrameImpl::ThreadPool_Error()
{
    return S_OK;
}
HRESULT CAsynFrameImpl::CreateIOperation(IBase** pBase)
{
    CIoOperationImpl* pObj = NULL;
    pObj = ALLOC_NEW CIoOperationImpl;
    rc_error(pObj != NULL, E_FAIL);
    return pObj->QueryInterface(IID_IOperation, (void**)pBase);
}
HRESULT CAsynFrameImpl::CreateITcpSocket(IBase** pBase)
{
    HRESULT hr = S_OK;

    CTcpSocketImpl* pObj = NULL;
    pObj = ALLOC_NEW CTcpSocketImpl;
    rc_error(pObj != NULL, E_FAIL);

    hr = pObj->CreateIoOperation(this);
    rc_error(hr == S_OK, E_FAIL);

    pObj->BindEvloop(get_service());

    return pObj->QueryInterface(IID_ITcpSocket, (void**)pBase);
}
HRESULT CAsynFrameImpl::CreateIUdpSocket(IBase** pBase)
{
    HRESULT hr = S_OK;

    CUdpSocketImpl* pObj = NULL;
    pObj = ALLOC_NEW CUdpSocketImpl;
    rc_error(pObj != NULL, E_FAIL);

    hr = pObj->CreateIoOperation(this);
    rc_error(hr == S_OK, E_FAIL);

    pObj->BindEvloop(get_service());

    return pObj->QueryInterface(IID_IUdpSocket, (void**)pBase);
}
HRESULT CAsynFrameImpl::CreateITcpListenSocket(IBase** pBase)
{
    CTcpListenSocketImpl* pObj = NULL;
    pObj = ALLOC_NEW CTcpListenSocketImpl;
    rc_error(pObj != NULL, E_FAIL);

    pObj->BindEvloop(get_service());

    return pObj->QueryInterface(IID_ITcpListen, (void**)pBase);
}
HRESULT CAsynFrameImpl::CreateITcpSocketSSL(IBase** pBase)
{
    HRESULT hr = S_OK;

    CTcpSocketSslImpl* pObj = NULL;
    pObj = ALLOC_NEW CTcpSocketSslImpl;
    rc_error(pObj != NULL, E_FAIL);

    hr = pObj->CreateIoOperation(this);
    rc_error(hr == S_OK, E_FAIL);

    pObj->BindEvloop(get_service());

    return pObj->QueryInterface(IID_ITcpSocketSsl, (void**)pBase);
}
HRESULT CAsynFrameImpl::CreateITcpListenSSLSocket(IBase** pBase)
{
    CTcpListenSocketSslImpl* pObj = NULL;
    pObj = ALLOC_NEW CTcpListenSocketSslImpl;
    rc_error(pObj != NULL, E_FAIL);

    pObj->BindEvloop(get_service());

    return pObj->QueryInterface(IID_ITcpSslListen, (void**)pBase);
}
HRESULT CAsynFrameImpl::CreateITimer(IBase** pBase)
{
    CTimerImpl* pObj = NULL;
    pObj = ALLOC_NEW CTimerImpl();
    rc_error(pObj != NULL, E_FAIL);
    return pObj->QueryInterface(IID_ITimer, (void**)pBase);
}
HRESULT CAsynFrameImpl::CreateIPipe(IBase** pBase)
{
    CPipeImpl* pObj = NULL;
    pObj = ALLOC_NEW CPipeImpl;
    rc_error(pObj != NULL, E_FAIL);
    return pObj->QueryInterface(IID_IPipe, (void**)pBase);
}
HRESULT CAsynFrameImpl::CreateISPipe(IBase** pBase)
{
    CSPipeImpl* pObj = NULL;
    pObj = ALLOC_NEW CSPipeImpl;
    rc_error(pObj != NULL, E_FAIL);
    return pObj->QueryInterface(IID_ISPipe, (void**)pBase);
}

HRESULT CAsynFrameImpl::InitEventLoop()
{
    return S_OK;
}
HRESULT CAsynFrameImpl::CreateEventLoop(ioevloop_t* ev, evloop_notify cb, void* user)
{
    rc_error(ev != NULL, E_FAIL);

    ioevloop_setctx(ev, user);

    return S_OK;
}
HRESULT CAsynFrameImpl::ExitEventLoop(ioevloop_t* ev)
{
    rc_error(ev != NULL, E_FAIL);
    return S_OK;
}

HRESULT CAsynFrameImpl::RunEventLoop(ioevloop_t* ev)
{
    rc_error(ev != NULL, E_FAIL);
    return S_OK;
}
ioevloop_t* CAsynFrameImpl::get_service()
{
    {
        SYNC_OBJ(&m_lock)
        m_eventindex++;
        if (m_eventindex == m_tpcount) {
            m_eventindex = 0;
        }
    }
    return this->m_evloop + m_eventindex;
}
